package com.smartian.v2.utils;

import android.text.TextUtils;


import com.smartian.v2.TextPattern;
import com.smartian.v2.model.DateTimeNode;

import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by tianweitong on 2020/3/15.
 */

public class DateTimeHelper  implements TextPattern {

    public static DateTimeNode findBestDateNode(List<DateTimeNode> dateTimeNodes, int Type) {
        if(dateTimeNodes==null || dateTimeNodes.size()==0) return null;
        Collections.sort(dateTimeNodes);
        for (int i=dateTimeNodes.size()-1;i>=0;i--){
            DateTimeNode dateTimeNode = dateTimeNodes.get(i);
            if(dateTimeNode.type==Type){
                return dateTimeNode;
            }

        }
        return null;
    }


    public static int getNext31DayMonth(int month) {
        int[] months = {1, 3, 5, 7, 8, 10, 12};
        int nextMonth = -1;
        for (int i = 0; i < months.length; i++) {
            if (months[i] > month) {
                nextMonth = months[i];
                break;
            }
        }
        if (month == 12) {
            nextMonth = 1;
        }
        return nextMonth;
    }

    public static boolean isLeapYear(int year) {
        boolean isLeapYear = (year % 4 == 0);
        isLeapYear = isLeapYear && (year % 100 != 0);
        isLeapYear = isLeapYear || (year % 400 == 0);
        return isLeapYear;
    }


    public static boolean has31Day(int month) {
        if (month == 0) {
            month = 12;
        }
        int[] months = {1, 3, 5, 7, 8, 10, 12};
        for (int i = 0; i < months.length; i++) {
            if (months[i] == month) {
                return true;
            }
        }
        return false;
    }

    public static String getFullDateTime(String date, String time) {

        if(TextUtils.isEmpty(date) && TextUtils.isEmpty(time)) return null;

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MILLISECOND,0);
        calendar.set(Calendar.SECOND,0);
        long todayTimeInMillis = calendar.getTimeInMillis();

        String[] dateParts = date.split("\\-");
        if(dateParts==null || dateParts.length!=3 && dateParts.length!=2){
            return null;
        }

        calendar.get(Calendar.YEAR);
        if(dateParts.length==3) {
            int year = DateTimeHelper.getIntegerValue(dateParts[0]);
            int month = DateTimeHelper.getIntegerValue(dateParts[1]);
            int day = DateTimeHelper.getIntegerValue(dateParts[2]);

            calendar.set(Calendar.YEAR, year);
            calendar.set(Calendar.MONTH, month - 1);
            calendar.set(Calendar.DAY_OF_MONTH, day);

        }else if(dateParts.length==2){

            int month = DateTimeHelper.getIntegerValue(dateParts[0]);
            int day = DateTimeHelper.getIntegerValue(dateParts[1]);

            calendar.set(Calendar.MONTH, month - 1);
            calendar.set(Calendar.DAY_OF_MONTH, day);

            while (calendar.getTimeInMillis()<todayTimeInMillis){
                calendar.add(Calendar.YEAR,1);
                calendar.set(Calendar.MONTH, month - 1);
                calendar.set(Calendar.DAY_OF_MONTH, day);
            }
            int M = calendar.get(Calendar.MONTH)+1;
            int D = calendar.get(Calendar.DAY_OF_MONTH);

            if(M!=month || D!=day){
                if(M==2 && D>=29 && !DateTimeHelper.isLeapYear(calendar.get(Calendar.YEAR))){
                    return null;
                }
                if(day==31 && !DateTimeHelper.has31Day(month)){
                    return null;
                }
            }
        }

        String[] timeParts = time.split(TextPattern.TIME_SEPATOR);
        if(timeParts==null || timeParts.length!=2){
            return null;
        }

        int hour = DateTimeHelper.getIntegerValue(timeParts[0]);
        int min = DateTimeHelper.getIntegerValue(timeParts[1]);
        calendar.set(Calendar.HOUR_OF_DAY,hour);
        calendar.set(Calendar.MINUTE,min);
        return TextPattern.sDateTimeFormat.format(calendar.getTimeInMillis());
    }

    public static String formatTime(String time) {
        if (TextUtils.isEmpty(time)) {
            return null;
        }

        String[] dateParts = time.split(TextPattern.TIME_SEPATOR);
        if (dateParts == null || dateParts.length != 2) {
            return null;

        }

        Calendar calendar = Calendar.getInstance();
        int hour = DateTimeHelper.getIntegerValue(dateParts[0]);
        int min = DateTimeHelper.getIntegerValue(dateParts[1]);

        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, min);

        return TextPattern.sTimeFormat.format(calendar.getTimeInMillis());
    }

    public static String formatWeekTime(String date, String time) {
        if(TextUtils.isEmpty(date) && TextUtils.isEmpty(time)) return null;

        Calendar calendar = Calendar.getInstance();
        String[] dateParts = date.split("\\-");
        if(dateParts==null || dateParts.length!=3){
            return null;
        }

        int year = DateTimeHelper.getIntegerValue(dateParts[0]);
        int month = DateTimeHelper.getIntegerValue(dateParts[1]);
        int day = DateTimeHelper.getIntegerValue(dateParts[2]);

        calendar.set(Calendar.YEAR,year);
        calendar.set(Calendar.MONTH,month-1);
        calendar.set(Calendar.DAY_OF_MONTH,day);

        String[] timeParts = time.split(TextPattern.TIME_SEPATOR);
        if(timeParts==null || timeParts.length!=2){
            return null;
        }

        int hour = DateTimeHelper.getIntegerValue(timeParts[0]);
        int min = DateTimeHelper.getIntegerValue(timeParts[1]);

        calendar.set(Calendar.HOUR_OF_DAY,hour);
        calendar.set(Calendar.MINUTE,min);

        return TextPattern.sWeekTimeFormat.format(calendar.getTimeInMillis());


    }

    public static String formatMonthTime(String date, String time) {
        if(TextUtils.isEmpty(date) && TextUtils.isEmpty(time)) return null;

        Calendar calendar = Calendar.getInstance();
        int day = DateTimeHelper.getIntegerValue(date);

        calendar.set(Calendar.DAY_OF_MONTH,day);

        String[] timeParts = time.split(TextPattern.TIME_SEPATOR);
        if(timeParts==null || timeParts.length!=2){
            return null;
        }

        int hour = DateTimeHelper.getIntegerValue(timeParts[0]);
        int min = DateTimeHelper.getIntegerValue(timeParts[1]);

        calendar.set(Calendar.HOUR_OF_DAY,hour);
        calendar.set(Calendar.MINUTE,min);

        return TextPattern.sMonthTimeFormat.format(calendar.getTimeInMillis());
    }


    public static String dateNumberTextToNumber(String dateText) {

        if(TextUtils.isEmpty(dateText)) return null;

        Calendar calendar = Calendar.getInstance();

        dateText = replaceChineseNumberToArbirc(dateText);

        for (int i=0;i<LOCAL_CHINESE_NUMBER_WORD.length;i++){
            dateText = dateText.replaceAll(String.format("%s%s",LOCAL_CHINESE_NUMBER_WORD[i],WORD_DAY),String.valueOf(i+1));
            dateText = dateText.replaceAll(String.format("%s%s",LOCAL_CHINESE_NUMBER_WORD[i],WORD_MONTH),String.valueOf(i+1));
            dateText = dateText.replaceAll(String.format("%s%s",LOCAL_CHINESE_NUMBER_WORD[i],WORD_YEAY),String.valueOf(i+1));
        }
        dateText = dateText.replaceAll(WORD_THIS_YEAR,String.valueOf(calendar.get(Calendar.YEAR))+WORD_YEAY);
        dateText = dateText.replaceAll(WORD_NEXT_YEAR,String.valueOf(calendar.get(Calendar.YEAR)+1)+WORD_YEAY);
        dateText = dateText.replaceAll(WORD_THIS_MONTH,String.valueOf(calendar.get(Calendar.MONTH)+1)+WORD_MONTH);

        if(TextPattern.REG_EXP_NEXT_MONTH.matcher(dateText).find()) {
            Matcher matcher = TextPattern.REG_EXP_YEAR_ONLY.matcher(dateText);
            if(!matcher.find()) {
                calendar.add(Calendar.MONTH,1);
                dateText = dateText.replaceAll(WORD_NEXT_MONTH, String.valueOf(calendar.get(Calendar.MONTH) + 1) + WORD_MONTH);
            }
        }
        dateText = dateText.replaceAll(WORD_TODAY,String.valueOf(calendar.get(Calendar.DAY_OF_MONTH))+WORD_DAY);

        Matcher matcher = TextPattern.REG_EXP_DATE_LEVEL_2.matcher(dateText);
        String resultText = WORD_EMPTY;
        while (matcher.find()){
            resultText = matcher.group();
        }

        if(TextUtils.isEmpty(resultText)) return WORD_EMPTY;

        resultText = resultText.replaceAll(WORD_DAY_ALIAS,WORD_DAY);
        if(!resultText.endsWith(WORD_DAY)){
            resultText = resultText.concat(WORD_DAY);
        }

        String year = DateTimeHelper.readPrevNumberAtFlag(resultText, TextPattern.WORD_YEAY);
        String month = DateTimeHelper.readPrevNumberAtFlag(resultText, TextPattern.WORD_MONTH);
        String day = DateTimeHelper.readPrevNumberAtFlag(resultText, TextPattern.WORD_DAY);

        Calendar current = Calendar.getInstance();
        int YEAR = current.get(Calendar.YEAR);

        Calendar  target = Calendar.getInstance();

        boolean hasYearField = !TextUtils.isEmpty(year);

        if(hasYearField){ //两位数的年份，19年10月25日->2019年10月25日
            int Y = DateTimeHelper.getIntegerValue(year);
            if(Y/100==0){
                Y = (YEAR/1000)*1000+Y;
            }

            target.set(Calendar.YEAR,Y);
        }
        if(!TextUtils.isEmpty(month)){
            int M = DateTimeHelper.getIntegerValue(month);
            if(!hasYearField){
                int currentMonth = target.get(Calendar.MONTH) + 1;
                if(currentMonth>M){
                    target.add(Calendar.YEAR,1);
                }
            }
            target.set(Calendar.MONTH,M-1);
        }
        if(!TextUtils.isEmpty(day)){

            int sM = target.get(Calendar.MONTH) + 1;
            int sD = DateTimeHelper.getIntegerValue(day);

            int THIS_DAY = target.get(Calendar.DAY_OF_MONTH);
            int THIS_YEAR = target.get(Calendar.YEAR);

            if(!hasYearField && sD<THIS_DAY){
                THIS_YEAR++;
                target.set(Calendar.YEAR,THIS_YEAR);
            }

            if(!hasYearField) {
                if (sM == 2) {
                    if (sD == 29) {
                        while (!DateTimeHelper.isLeapYear(THIS_YEAR)) {
                            THIS_YEAR++;
                        }
                        target.set(Calendar.YEAR, THIS_YEAR);
                    } else if (sD > 29) {
                        return null;
                    }
                } else {
                    if (sD == 31 && !has31Day(sM)) {
                        return null;
                    }
                }
            }

            target.set(Calendar.DAY_OF_MONTH,sD);
        }

        return sDateFormat.format(target.getTime());
    }
    public static String replaceChineseNumberToArbirc(String dateText) {
        for (int i = 0; i< TextPattern.CHINESE_WORD_NUMBER.length; i++){
            String ch = TextPattern.CHINESE_WORD_NUMBER[i];
            dateText = dateText.replaceAll(ch,String.valueOf(i));
        }
        for (int i=0;i<CHINES_NUMBER_UNITS.length;i++) {
            dateText = makeUnitWordToNumber(dateText, CHINES_NUMBER_UNITS[i], (int) Math.pow(10,i+1));
        }
        return dateText;
    }

    private static String makeUnitWordToNumber(String message, String unit, int delta) {

        if(TextUtils.isEmpty(message)) {
            return TextPattern.WORD_EMPTY;
        }
        if(!message.contains(unit)) {
            return message;
        }

        for (int i=1;i<10;i++){  //时间
            for (int j=1;j<delta;j++){
                int dx = delta / 10;
                if(j<dx) {
                    if (message.contains(i + unit +"0"+ j)) {
                        message = message.replaceAll(i + unit+"0" + j, i + "0" + j);
                    }
                }else {
                    if (message.contains(i + unit + j)) {
                        message = message.replaceAll(i + unit + j, i + "" + j);
                    }
                }
            }
            if(message.contains(i+unit)) {
                message = message.replaceAll(i + unit, (i*delta)+"");
            }
        }
        for (int j=1;j<delta;j++){
            if(message.contains(unit+j)) {
                message = message.replaceAll(unit+j,"1"+j);
            }
        }
        message = message.replaceAll(unit,delta+"");
        return message;
    }
    public static String getToday() {
        Calendar today = Calendar.getInstance();
        return TextPattern.sDateFormat.format(today.getTime());
    }
    public static String getCurrentDateTime() {
        Calendar today = Calendar.getInstance();
        return TextPattern.sDateTimeFormat.format(today.getTime());
    }
    public static String getTomorrow() {
        Calendar today = Calendar.getInstance();
        today.add(Calendar.DAY_OF_MONTH,1);
        return TextPattern.sDateFormat.format(today.getTime());
    }
    public static String getTomorrowTomorrow() {
        Calendar today = Calendar.getInstance();
        today.add(Calendar.DAY_OF_MONTH,2);
        return TextPattern.sDateFormat.format(today.getTime());
    }
    public static String readFirstNumber(String textWithNumber) {

        if(TextUtils.isEmpty(textWithNumber)) return WORD_EMPTY;
        StringBuilder sb = new StringBuilder();
        for (int i=0;i<textWithNumber.length();i++){
            char ch = textWithNumber.charAt(i);
            if(ch>='0' && ch<='9'){
                sb.append(ch);
            }else{
                if(sb.length()>0) break;
            }
        }
        return sb.toString();
    }
    public static String makeWeekToDate(String weekDay) {

        if(TextUtils.isEmpty(weekDay)) return WORD_EMPTY;
        int dayOfWeek = Integer.parseInt(weekDay);
        Calendar calendar = Calendar.getInstance();
        int weekday = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        if(weekday==0){
            weekday = 7;
        }
        int days = dayOfWeek - weekday;
        if(days>=0){
            calendar.add(Calendar.DAY_OF_WEEK,days);
        }else{
            calendar.add(Calendar.DAY_OF_WEEK,days+7);
        }
        return sDateFormat.format(calendar.getTimeInMillis());
    }
    public static String timeNumberToNumber(String time) {
        if(TextUtils.isEmpty(time)) return WORD_EMPTY;
        String timeText = replaceChineseNumberToArbirc(time);

        timeText = timeText.replaceAll(TextPattern.WORD_HOUR_POINT,":").replaceAll(TextPattern.WORD_MINUTE,"");
        timeText = timeText.replaceAll(TextPattern.WORD_TIME_AFTER,"");
        Matcher matcher = TextPattern.REG_EXP_TIME.matcher(timeText);
        if(matcher.matches()){
            return timeText;
        }
        return WORD_EMPTY;
    }

    public static String fourPiceTimeNumberToNumber(String time) {

        if(TextUtils.isEmpty(time)) return WORD_EMPTY;
        String timeText = replaceChineseNumberToArbirc(time);

        timeText = timeText.replaceAll(TextPattern.WORD_HOUR_POINT,":")
                .replaceAll(TextPattern.WORD_MINUTE,"");

        timeText = timeText.replaceAll(TextPattern.WORD_TIME_MID_DAY,"12:");

        for (int i=0;i<24;i++) {
            for (int k = 1; k < 4; k++) {
                String word = i + ":" + k + "刻";
                if (!timeText.contains(word)) {
                    continue;
                }
                timeText = timeText.replaceAll(word, i + ":" + (k * 15) + "");
            }
        }
        Matcher matcher = TextPattern.REG_EXP_TIME.matcher(timeText);
        if(matcher.matches()){
            return timeText;
        }
        return WORD_EMPTY;
    }

    public static String entireTimeNumberToNumber(String time) {
        if(TextUtils.isEmpty(time)) return WORD_EMPTY;
        String timeText = replaceChineseNumberToArbirc(time);

        if(timeText.contains(WordConstant.DOT_HALF_TEXT)) {
            timeText = timeText.replaceAll(WordConstant.DOT_HALF_TEXT, WordConstant.DOT_HALF_TEXT_2);
        }
        String  min = readNextNumberAtFlag(timeText,TextPattern.WORD_HOUR_POINT);
        String  hour  = readFirstNumber(timeText);
        int numHour = getIntegerValue(hour);
        int numMinute = getIntegerValue(min);
        if(numHour==24){
            numHour = 0;
        }
        return numHour+":"+numMinute;

    }

    public static int getIntegerValue(String numText) {

        try{
            if(TextUtils.isEmpty(numText)) return 0;
            if(!TextUtils.isDigitsOnly(numText)) return 0;
            return  Integer.parseInt(numText);
        }catch (Exception e){
            e.printStackTrace();
        }

        return 0;
    }
    public static String readPrevNumberAtFlag(String text, String word) {
        if(!text.contains(word)) return null;
        int startIndex = text.indexOf(word);
        String strNum = "";
        for (int i=startIndex-1;i>=0;i--){
            char ch = text.charAt(i);
            if(ch>='0' && ch<='9'){
                strNum = ch+strNum;
            }else{
                if(strNum.length()>0) break;
            }
        }
        return strNum;
    }
    public static String readNextNumberAtFlag(String text, String word) {
        if(!text.contains(word)) return null;
        int startIndex = text.lastIndexOf(word) + word.length();
        String strNum = "";
        for (int i=startIndex;i<text.length();i++){
            char ch = text.charAt(i);
            if(ch>='0' && ch<='9'){
                strNum = strNum+ch;
            }else{
                if(strNum.length()>0) break;
            }
        }
        return strNum;
    }

    public static String getCurrentTime( ) {
        return TextPattern.sTimeFormat.format(System.currentTimeMillis());
    }

    public static DateTimeNode tryGetYearNode(String sourceText) {

        DateTimeNode dateTimeNode = new DateTimeNode();
        dateTimeNode.index = -1;
        dateTimeNode.type = DateTimeNode.TYPE_LOCATOR;

        if(TextUtils.isEmpty(sourceText)) {
            return dateTimeNode;
        }

        String[] YEAR_MATCHES = new String[]{
                TextPattern.WORD_THIS_YEAR,
                TextPattern.WORD_NEXT_YEAR,
                TextPattern.WORD_NEXT_NEXT_YEAR
        };

        Calendar calendar = Calendar.getInstance();
        int YEAR = calendar.get(Calendar.YEAR);

        for (int i=0;i<YEAR_MATCHES.length;i++){
            Matcher matcher = Pattern.compile(YEAR_MATCHES[i]).matcher(sourceText);
            if(matcher.find()){
                String yearName = matcher.group();
                int startIndex = matcher.start();
                if(startIndex>=dateTimeNode.index) {
                    dateTimeNode.text = yearName;
                    dateTimeNode.index = startIndex;
                    dateTimeNode.resultText = String.format("%s", (YEAR + i));
                }
            }
        }

        Matcher matcher = TextPattern.REG_EXP_YEAR_ONLY.matcher(sourceText);
        int THIS_YEAR = Calendar.getInstance().get(Calendar.YEAR);

        while (matcher.find()){
            String group = matcher.group();
            int startIndex = matcher.start();

            String year = DateTimeHelper.readPrevNumberAtFlag(group, TextPattern.WORD_YEAY);
            int Y = DateTimeHelper.getIntegerValue(year);

            if(Y/100==0){
                Y = (THIS_YEAR/1000)*1000 + Y;
            }
            THIS_YEAR = Y;

            if(startIndex>=dateTimeNode.index) {
                dateTimeNode.text = group;
                dateTimeNode.index = startIndex;
                dateTimeNode.resultText = String.format("%s", (THIS_YEAR));
            }
        }
        return dateTimeNode;
    }
}
